import json

from django.db import transaction
from django.shortcuts import render

# Create your views here.
from django_celery_beat.models import PeriodicTask
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response

from apitest.models import EnvInfo, ProjectInfo, ModuleInfo, TestApiInfo, TestApiResult, TestCase
from apitest.serializers import EnvInfoModelSerializer, ProjectInfoSerializer, ModuleInfoSerializer, \
    TestApiInfoSerializer, TestApiResultSerializer, TestApiInfoImportSerializer, TestApiInfoExportSerializer, \
    TestCaseSerializer
from dvadmin.utils.RequestUtil import RequestUtil
from dvadmin.utils.json_response import DetailResponse, ErrorResponse, SuccessResponse
from dvadmin.utils.viewset import CustomModelViewSet


class EnvInfoModelViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = EnvInfo.objects.all()
    serializer_class = EnvInfoModelSerializer

    # 自定义方法
    @action(methods=['put'], detail=True)
    @transaction.atomic
    def setDefault(self, request, pk):
        toSet = request.data.get('default', False)
        if toSet:
            EnvInfo.objects.filter(id=pk).update(default=True)
            EnvInfo.objects.exclude(id=pk).update(default=False)
        else:
            EnvInfo.objects.filter(id=pk).update(default=False)
        return DetailResponse(data="修改成功")


class ProjectInfoViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = ProjectInfo.objects.all()
    serializer_class = ProjectInfoSerializer


class ModuleInfoViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = ModuleInfo.objects.all()
    serializer_class = ModuleInfoSerializer


class TestApiInfoViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = TestApiInfo.objects.all()
    serializer_class = TestApiInfoSerializer

    # 导出
    export_field_label = {
        "name": "测试用例",
        'method_name': '接口类型',
        "url": "请求地址",
        'create_datetime': '创建时间'
    }
    export_serializer_class = TestApiInfoExportSerializer

    # excel 上传业务
    import_serializer_class = TestApiInfoImportSerializer
    # 下载的模版定义  前面字段 是model字段
    import_field_dict = {
        "name": "测试用例",
        "url": "请求地址",
        "method": {
            "title": "协议类型",
            "choices": {
                "data": {"GET": 0, "POST": 1, "PUT": 2, 'DELETED': 3},
            }
        },
        "headers": "头部信息(json)",
        "params": "params类型字段(kv)",
        "jsonbody": "json类型字段(json)",
        "verification": "检查点",
        'extract': '关联字段',
        "project_belong": {"title": "工程信息",
                           "choices": {"queryset": ProjectInfo.objects.all(), "values_name": "project_name"}},
        "module_belong": {"title": "模块信息",
                          "choices": {"queryset": ModuleInfo.objects.all(), "values_name": "module_name"}},
    }

    @action(methods=['put'], detail=True)
    @transaction.atomic
    def apiTest(self, request, pk):
        print(pk)
        apiinfo = TestApiInfo.objects.get(id=pk)
        if apiinfo:
            api = RequestUtil()
            env = request.data.get('env')
            if env is not None:
                paramsbody  = env.get('paramsbody')
                if paramsbody is not None and paramsbody!='':
                    api.var_pool_data = json.loads(paramsbody)
            url = apiinfo.url
            headers = apiinfo.headers
            verification = apiinfo.verification
            extract = apiinfo.extract

            if apiinfo.params_type == 1:
                # 数据格式 data  id=1&name=test
                params_dic = {}
                if apiinfo.params is not None and apiinfo.params!='':
                    for item in apiinfo.params.split("&"):
                        k = item.split("=")[0]
                        v = item.split("=")[1]
                        params_dic[k] = v
                api.send_request(apiinfo.get_method_display(), url,
                                 verification=verification, case_desc=apiinfo.description,
                                 headers=headers, data=params_dic)
            elif apiinfo.params_type == 2 and apiinfo.jsonbody!='':
                api.send_request(apiinfo.get_method_display(), url,
                                 verification=verification, case_desc=apiinfo.description,
                                 headers=headers, json=apiinfo.jsonbody)
            else:
                api.send_request(apiinfo.get_method_display(), url,
                                 verification=verification, case_desc=apiinfo.description,
                                 headers=headers)

            print("测试结果")
            print(api.get_result())
            # 返回结果有异常
            if api.get_result().get('code') == 0:
                return ErrorResponse(msg=api.get_result().get('response'))
            # 写数据库 insert  orm
            testApiResult = TestApiResult()
            testApiResult.api_belong = apiinfo
            testApiResult.project_belong = apiinfo.project_belong
            testApiResult.module_belong = apiinfo.module_belong
            testApiResult.took_time = api.get_result().get("took_time")
            testApiResult.result = api.get_result().get("response")
            testApiResult.verification = api.get_result().get("check_result")
            testApiResult.env_belong = EnvInfo.objects.get(id=env.get('id'))
            testApiResult.save()
        return DetailResponse(data="测试成功")

    @action(methods=['put'], detail=False)
    def multiple_test(self, request, *args, **kwargs):
        request_data = request.data
        keys = request_data.get('keys', None)
        if keys:
            env = request.data.get('env')
            # TestApiInfo.objects.filter()
            alltestcases = self.get_queryset().filter(id__in=keys)
            for apiinfo in alltestcases:
                api = RequestUtil()
                if env is not None:
                    paramsbody = env.get('paramsbody')
                    if paramsbody is not None and paramsbody != '':
                        api.var_pool_data = json.loads(paramsbody)
                url = apiinfo.url
                headers = apiinfo.headers
                verification = apiinfo.verification

                if apiinfo.params_type == 1 and apiinfo.params!='':
                    # 数据格式 data  id=1&name=test
                    params_dic = {}
                    if apiinfo.params is not None:
                        for item in apiinfo.params.split("&"):
                            k = item.split("=")[0]
                            v = item.split("=")[1]
                            params_dic[k] = v
                    api.send_request(apiinfo.get_method_display(), url,
                                     verification=verification, case_desc=apiinfo.description,
                                     headers=headers, data=params_dic)
                elif apiinfo.params_type == 2:
                    api.send_request(apiinfo.get_method_display(), url,
                                     verification=verification, case_desc=apiinfo.description,
                                     headers=headers, json=apiinfo.jsonbody)
                else:
                    api.send_request(apiinfo.get_method_display(), url,
                                     verification=verification, case_desc=apiinfo.description,
                                     headers=headers)

                print("测试结果")
                print(api.get_result())
                # 返回结果有异常
                # if api.get_result().get('code') == 0:
                #     return ErrorResponse(msg=api.get_result().get('response'))
                # 写数据库 insert  orm
                testApiResult = TestApiResult()
                testApiResult.api_belong = apiinfo
                testApiResult.project_belong = apiinfo.project_belong
                testApiResult.module_belong = apiinfo.module_belong
                testApiResult.took_time = api.get_result().get("took_time")
                result = api.get_result().get("response")
                testApiResult.env_belong = EnvInfo.objects.get(id=env.get('id'))
                if len(result) > 200:
                    result = result[0:200]
                testApiResult.result = result
                testApiResult.verification = api.get_result().get("check_result")
                testApiResult.save()

            return SuccessResponse(data=[], msg="测试完成")
        else:
            return ErrorResponse(msg="未获取测试数据")


class TestApiResultViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = TestApiResult.objects.all()
    serializer_class = TestApiResultSerializer


    @action(methods=['get'], detail=False)
    def count(self, request):
        env  = request.query_params.get('env')
        if env:
            evn_reuslt = self.get_queryset().filter(env_belong=env).values()
        else:
            evn_reuslt = self.get_queryset().values()

        evn_successs = list(filter(lambda elem:elem['verification']=='检查成功',evn_reuslt))
        evn_fail = list(filter(lambda elem: elem['verification'] == '检查失败', evn_reuslt))
        evn_skip = list(filter(lambda elem: elem['verification'] == '没有设置检查点', evn_reuslt))
        pie=[]
        pie.append({'name':'检查成功','value':len(evn_successs)})
        pie.append({'name': '检查失败','value':len(evn_fail)})
        pie.append({'name': '跳过检查','value':len(evn_skip)})
        #完成率 select  from  distinct(api_belogn)
        api_testd_count= len(evn_reuslt.values('api_belong').distinct())
        #所有接口
        all_api_count = len(TestApiInfo.objects.all())

        result_data={}
        result_data['apicount'] = pie
        result_data['allApis'] = all_api_count
        result_data['testApis'] = api_testd_count
        result_data['finshed'] = round(api_testd_count*100/all_api_count)
        result_data['total'] = len(evn_reuslt)

        return DetailResponse(data=result_data,msg='正常返回')




#请求 ->view (方法 自己重写create)
class TestCaseViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = TestCase.objects.all()
    serializer_class = TestCaseSerializer

    @action(methods=['put'], detail=True)
    @transaction.atomic
    def caseTest(self, request, pk):
        testcase = TestCase.objects.get(id=pk)
        if testcase:
            apis = testcase.apis.all()
            api = RequestUtil()
            env = request.data.get('env')
            if env is not None:
                paramsbody = env.get('paramsbody')
                if paramsbody is not None and paramsbody != '':
                    api.var_pool_data = json.loads(paramsbody)
            for apiinfo in apis:
                url = apiinfo.url
                headers = apiinfo.headers
                verification = apiinfo.verification
                extract = apiinfo.extract

                if apiinfo.params_type == 1:
                    # 数据格式 data  id=1&name=test
                    params_dic = {}
                    if apiinfo.params is not None and apiinfo.params!='':
                        for item in apiinfo.params.split("&"):
                            k = item.split("=")[0]
                            v = item.split("=")[1]
                            params_dic[k] = v
                    api.send_request(apiinfo.get_method_display(), url,
                                     verification=verification, case_desc=apiinfo.description,
                                     headers=headers, data=params_dic, extract=extract)
                elif apiinfo.params_type == 2:
                    api.send_request(apiinfo.get_method_display(), url,
                                     verification=verification, case_desc=apiinfo.description,
                                     headers=headers, json=apiinfo.jsonbody, extract=extract)
                else:
                    api.send_request(apiinfo.get_method_display(), url,
                                     verification=verification, case_desc=apiinfo.description,
                                     headers=headers, extract=extract)

                print("测试结果")
                print(api.get_result())
                # 返回结果有异常
                # if api.get_result().get('code') == 0:
                #     return ErrorResponse(msg=api.get_result().get('response'))
                # 写数据库 insert  orm
                testApiResult = TestApiResult()
                testApiResult.case_belong = testcase
                testApiResult.api_belong = apiinfo
                testApiResult.project_belong = apiinfo.project_belong
                testApiResult.module_belong = apiinfo.module_belong
                testApiResult.took_time = api.get_result().get("took_time")
                testApiResult.env_belong= EnvInfo.objects.get(id=env.get('id'))
                result = api.get_result().get("response")
                if len(result) > 200:
                    result = result[0:200]
                testApiResult.result = result
                testApiResult.verification = api.get_result().get("check_result")
                testApiResult.save()
            return SuccessResponse(data=[], msg="测试完成")

    @transaction.atomic
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        #删除对应定时任务
        taskid = instance.task_id
        if taskid is not None and taskid!='':
          try:
              periodicTask = PeriodicTask.objects.get(id=taskid)
              periodicTask.delete()
          except Exception as e:
              print(e)
              pass
        instance.delete()
        return SuccessResponse(data=[], msg="测试完成")


    @action(methods=['delete'],detail=False)
    @transaction.atomic
    def multiple_delete(self,request,*args,**kwargs):
        request_data = request.data
        keys = request_data.get('keys',None)
        task_list = self.get_queryset().filter(id__in=keys).values_list("task_id",flat=True)
        if keys:
            PeriodicTask.objects.filter(id__in=task_list).delete()
            self.get_queryset().filter(id__in=keys).delete()
            return SuccessResponse(data=[], msg="删除成功")
        else:
            return ErrorResponse(msg="未获取到keys字段")